/*
 * @Author: 彭林
 * @Date: 2020-12-23 18:31:34
 * @LastEditTime: 2021-07-01 15:45:52
 * @LastEditors: 彭林
 * @Description:
 * @FilePath: /src/saas-app/app/service/upload.go
 */
package service

import (
	"fmt"
	"io"
	"os"
	"saas-app/app/config"
	"strings"

	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	"github.com/gogf/gf/net/ghttp"
	uuid "github.com/satori/go.uuid"
	"github.com/spf13/cast"
)

var endpoint = config.Config.Oss.Aliyun.Endpoint
var accessKeyId = config.Config.Oss.Aliyun.AccessKeyID
var accessKeySecret = config.Config.Oss.Aliyun.AccessKeySecret
var bucketName = config.Config.Oss.Aliyun.BucketName
var fileEndpoint = config.Config.Oss.Aliyun.FileEndpoint

type UploadRepository interface {
	OSSUpLoad(file *ghttp.UploadFile) string
	SaveUploadedFile(file *ghttp.UploadFile, dst string) error
}

type upload struct{}

func UploadService() UploadRepository {
	return &upload{}
}

func (u upload) OSSUpLoad(file *ghttp.UploadFile) (name string) {

	u1 := cast.ToString(uuid.NewV4())

	fmt.Println("filename:,", file.Filename)
	fmt.Println("endpoint:", endpoint)
	fmt.Println("accessKeyId:", accessKeyId)
	fmt.Println("accessKeySecret:", accessKeySecret)
	fmt.Println("bucketName:", bucketName)
	fmt.Println("fileEndpoint:", fileEndpoint)

	prefix := "." + strings.Split(file.Filename, ".")[1]
	dst := "./" + u1 + prefix

	if err := UploadService().SaveUploadedFile(file, dst); err != nil {
		panic(err)
	}

	// 创建OSSClient实例。
	client, err := oss.New(endpoint, accessKeyId, accessKeySecret)
	if err != nil {
		panic(err)
	}

	// 获取存储空间。
	bucket, err := client.Bucket(bucketName)
	if err != nil {
		panic(err)
	}

	// 读取本地文件。
	fd, err := os.Open(dst)
	if err != nil {
		panic(err)
	}

	defer fd.Close()
	url := u1 + prefix
	// 上传文件流。
	err = bucket.PutObject(url, fd)
	if err != nil {
		panic(err)
	}

	err = os.Remove(dst)

	if err != nil {
		os.Exit(-1)
		panic("上传成功，临时文件删除失败")
	}

	return (fileEndpoint + "/" + url)
}

func (u upload) SaveUploadedFile(file *ghttp.UploadFile, dst string) error {
	src, err := file.Open()
	if err != nil {
		return err
	}
	defer src.Close()
	//创建 dst 文件
	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer out.Close()
	// 拷贝文件
	_, err = io.Copy(out, src)
	return err
}
